﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ScheduleMaker.DB.Domain.Core;
using ScheduleMaker.DB.CoreDAO;
using System.Diagnostics;

namespace ScheduleMaker
{
    public partial class smStudentForm : Form
    {

        const int columnMinimumWidth = 190;

        IList<DB.Domain.Core.Group> groups;
        IList<DB.Domain.Core.Classroom> classrooms;
        IList<DB.Domain.Core.Teacher> teachers;
        IList<DB.Domain.Core.Day> days;
        IList<DB.Domain.Core.ClassHour> classHours;
        IList<DB.Domain.Core.Subject> subjects;
        IList<DB.Domain.Core.Category> categories;

        IList<TeacherInaccessibility> teacherInnaccessibility = new List<TeacherInaccessibility>();
        IList<ClassroomInaccessibility> classroomInaccessibility = new List<ClassroomInaccessibility>();

        private DateTime emergencyScheduleWeek;
        private bool boolEmergencyScheduleWeek = false;
        private class TeacherInaccessibility
        {
            static IList<DB.Domain.Core.ClassHour> classHours = null;
            public DB.Domain.Core.Teacher teacher;
            public DateTime from;
            public DateTime to;
            public string comboBox;
            public DB.Domain.Core.Day day;
            IList<DB.Domain.Core.ClassHour> hours;
            public DB.Domain.Core.ClassHour hourBegin;
            public DB.Domain.Core.ClassHour hourEnd;

            public TeacherInaccessibility(DB.Domain.Core.Teacher teacher_p, DateTime from_p, DateTime to_p, DB.Domain.Core.Day day_p, string comboBox_p)
            {
                this.teacher = teacher_p;
                this.from = from_p;
                this.to = to_p;
                this.comboBox = comboBox_p;
                this.day = day_p;
                fillClassHours();
            }
            private void fillClassHours()
            {
                if (TeacherInaccessibility.classHours == null)
                {
                    DB.CoreDAO.ClassHourDAO dao = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type); 
                    classHours = dao.getAll();
                }

                this.hours = new List<DB.Domain.Core.ClassHour>();
                foreach (var classHour in TeacherInaccessibility.classHours)
                {
                    if (this.from.TimeOfDay <= classHour.End && this.to.TimeOfDay >= classHour.End)
                    {
                        this.hours.Add(classHour);
                        //Console.WriteLine("ti hour added: " + classHour.Begin.ToString() + " - " + classHour.End.ToString());
                    }
                    else if (this.to.TimeOfDay >= classHour.Begin && classHour.Begin >= this.from.TimeOfDay)
                    {
                        this.hours.Add(classHour);
                       // Console.WriteLine("ti hour added: " + classHour.Begin.ToString() + " - " + classHour.End.ToString());
                    }
                }
                IEnumerable<DB.Domain.Core.ClassHour> query = classHours.OrderBy(hour => hour.Begin);
                this.hourBegin = query.First();
                Console.WriteLine("ti hour First: " + this.hourBegin.ToString());
                this.hourEnd = query.Last();
                Console.WriteLine("ti hour End: " + this.hourBegin.ToString());
            }
            public DB.Domain.Core.TeacherUnavailability getTeacherUnavailabilityObject()
            {
                DB.Domain.Core.TeacherUnavailability teacherUnavailability;
                if (ConfigManager.ConfigManager.getConfiguration().Type == ConfigManager.Mode.School) {
                        teacherUnavailability = new  DB.Domain.TeacherUnavailabilitySchool();
                } else {
                        teacherUnavailability = new DB.Domain.TeacherUnavailabilityUniversity();
                      
                }
                teacherUnavailability.Begin = this.hourBegin;
                teacherUnavailability.End = this.hourEnd;
                teacherUnavailability.Date = this.from.Ticks;
                teacherUnavailability.Day = this.day;
                teacherUnavailability.Teacher = this.teacher;
                return teacherUnavailability;
            }

            public bool hasHour(ClassHour hour)
            {
                foreach (var classHour in this.hours)
                {
                    if (hour.Id == classHour.Id)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        private class ClassroomInaccessibility
        {
            static IList<DB.Domain.Core.ClassHour> classHours = null;
            public DB.Domain.Core.Classroom classroom;
            public DateTime from;
            public DateTime to;
            public string comboBox;
            public DB.Domain.Core.Day day;
            IList<DB.Domain.Core.ClassHour> hours;
            public DB.Domain.Core.ClassHour hourBegin;
            public DB.Domain.Core.ClassHour hourEnd;

            public ClassroomInaccessibility(DB.Domain.Core.Classroom classroom_p, DateTime from_p, DateTime to_p, DB.Domain.Core.Day day_p, string comboBox_p)
            {
                this.classroom = classroom_p;
                this.from = from_p;
                this.to = to_p;
                this.comboBox = comboBox_p;
                this.day = day_p;
            }
            private void fillClassHours()
            {
                if (ClassroomInaccessibility.classHours == null)
                {
                    DB.CoreDAO.ClassHourDAO dao = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type); ;
                    classHours = dao.getAll();
                }

                this.hours = new List<DB.Domain.Core.ClassHour>();
                foreach (var classHour in ClassroomInaccessibility.classHours)
                {
                    if (this.from.TimeOfDay <= classHour.End && this.to.TimeOfDay >= classHour.End)
                    {
                        this.hours.Add(classHour);
                        Console.WriteLine("ci hour added: " + classHour.Begin.ToString() + " - " + classHour.End.ToString());
                    }
                    else if (this.to.TimeOfDay >= classHour.Begin && classHour.Begin >= this.from.TimeOfDay)
                    {
                        this.hours.Add(classHour);
                        Console.WriteLine("ci hour added: " + classHour.Begin.ToString() + " - " + classHour.End.ToString());
                    }
                }
                IEnumerable<DB.Domain.Core.ClassHour> query = classHours.OrderBy(hour => hour.Begin);
                this.hourBegin = query.First();
                Console.WriteLine("ti hour First: " + this.hourBegin.ToString());
                this.hourEnd = query.Last();
                Console.WriteLine("ti hour End: " + this.hourBegin.ToString());
            }

            public DB.Domain.Core.ClassroomUnavailability getClassroomUnavailabilityObject()
            {
                DB.Domain.Core.ClassroomUnavailability classroomUnavailability;
                if (ConfigManager.ConfigManager.getConfiguration().Type == ConfigManager.Mode.School)
                {
                    classroomUnavailability = new DB.Domain.ClassroomUnavailabilitySchool();
                }
                else
                {
                    classroomUnavailability = new DB.Domain.ClassroomUnavailabilityUniversity();
                }
                classroomUnavailability.Begin = this.hourBegin;
                classroomUnavailability.End = this.hourEnd;
                classroomUnavailability.Date = this.from.Ticks;
                classroomUnavailability.Day = this.day;
                classroomUnavailability.Classroom = this.classroom;
                return classroomUnavailability;
            }

            public bool hasHour(ClassHour hour)
            {
                foreach (var classHour in this.hours)
                {
                    if (hour.Id == classHour.Id)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        public smStudentForm()
        {
            InitializeComponent();

            // Ładujemy dane do comboboxów.
            this.tabControl.TabPages.Remove(this.tabEmergencySchedule);
            this.tabControl.TabPages.Remove(this.tabManagingHours);
            if (ConfigManager.ConfigManager.getConfiguration().Type == ConfigManager.Mode.University)
            {
                this.comboBoxGroups.Visible = false;
                this.lblStudBrowGr.Visible = false;
                this.tabControl.TabPages.Remove(this.tabSettings);
                //this.tabSettings.

            }
            else
            {
                loadGroups();
            }
            loadClassrooms();
            loadTeachers();
            loadSubjects();
            getCategortyList();
            // Ładujemy dni i godziny do grida.
            grid.Rows.Clear();
            grid.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
            grid.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            loadDays();
            loadHours();
            fillClassHours();


            // Zablokować edycję grida.


            //BEGIN:ScheduleTabPage
            loadEmergencyScheduleTabPage();
            //END:ScheduleTabPage
        }

        // Pobieranie - kategori
        public void getCategortyList()
        {

            if (ConfigManager.ConfigManager.getConfiguration().Type == ConfigManager.Mode.University)
            {
                CategoryDAO categoryDao = DB.DAOFactory.getCategoryDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                categories = categoryDao.getAll();
            }
            else
            {
                //lbGroup.Items.Add("Na uczelni nie ma grup");
            }
        }

        private void loadEmergencyScheduleTabPage()
        {
            // do przeniesienia
            gridTeacherInaccessibility.Rows.Clear();
            gridTeacherInaccessibility.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
            gridTeacherInaccessibility.DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopLeft;
            gridTeacherInaccessibility.ReadOnly = true;
            gridTeacherInaccessibility.AllowUserToAddRows = false;
            gridTeacherInaccessibility.ColumnCount = 3;
            gridTeacherInaccessibility.Columns[0].Name = "Prowadzący";
            gridTeacherInaccessibility.Columns[0].MinimumWidth = 150;
            gridTeacherInaccessibility.Columns[1].Name = "Od:";
            gridTeacherInaccessibility.Columns[1].MinimumWidth = 150;
            gridTeacherInaccessibility.Columns[2].Name = "Do:";
            gridTeacherInaccessibility.Columns[2].MinimumWidth = 150;
            dtpickFromTeacherInaccessibility.Format = dtpickToTeacherInaccessibility.Format = DateTimePickerFormat.Custom;
            dtpickFromTeacherInaccessibility.CustomFormat = dtpickToTeacherInaccessibility.CustomFormat = "dd-MM-yyyy HH:mm";

            dataGridViewClassroomInaccessibility.Rows.Clear();
            dataGridViewClassroomInaccessibility.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
            dataGridViewClassroomInaccessibility.DefaultCellStyle.Alignment = DataGridViewContentAlignment.TopLeft;
            dataGridViewClassroomInaccessibility.ReadOnly = true;
            dataGridViewClassroomInaccessibility.AllowUserToAddRows = false;
            dataGridViewClassroomInaccessibility.ColumnCount = 3;
            dataGridViewClassroomInaccessibility.Columns[0].Name = "Sala:";
            dataGridViewClassroomInaccessibility.Columns[0].MinimumWidth = 150;
            dataGridViewClassroomInaccessibility.Columns[1].Name = "Od:";
            dataGridViewClassroomInaccessibility.Columns[1].MinimumWidth = 150;
            dataGridViewClassroomInaccessibility.Columns[2].Name = "Do:";
            dataGridViewClassroomInaccessibility.Columns[2].MinimumWidth = 150;
            dateTimePickerFromClassroomInaccessibility.Format = dateTimePickerToClassroomInaccessibility.Format = DateTimePickerFormat.Custom;
            dateTimePickerFromClassroomInaccessibility.CustomFormat = dateTimePickerToClassroomInaccessibility.CustomFormat = "dd-MM-yyyy HH:mm";
            //

            loadTeachersEmergencyScheduleTabPage();
            loadClassroomsEmergencyScheduleTabPage();
        }

        private void loadTeachersEmergencyScheduleTabPage()
        {
            TeacherDAO teacherDAO = DB.DAOFactory.getTeacherDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            teachers = teacherDAO.getAll();
            foreach (var elem in teachers)
            {
                //comboBoxTeachers.Items.Add(elem.Id + " - " + elem.Name);
                // do przeniesienia
                comboBoxAddTeacherInaccessibility.Items.Add(elem.Id + " - " + elem.Name);
                //
            }
            //combooxTeachers.DropDownStyle = ComboBoxStyle.DropDownList;
            // do przeniesienia
            comboBoxAddTeacherInaccessibility.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBoxAddTeacherInaccessibility.SelectedIndex = 0;
            //
        }
        private void loadClassroomsEmergencyScheduleTabPage()
        {
            DB.CoreDAO.ClassroomDAO classroomDAO = DB.DAOFactory.getClassroomDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            classrooms = classroomDAO.getAll();
            foreach (var elem in classrooms)
            {
                comboBoxAddClassroomInaccessibility.Items.Add(elem.Id + " - " + elem.Name);
            }
            comboBoxAddClassroomInaccessibility.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBoxAddClassroomInaccessibility.SelectedIndex = 0;

        }

        private void loadSubjects()
        {

            // wczytujemy grupy


            DB.CoreDAO.SubjectDAO subjectDAO = DB.DAOFactory.getSubjectDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            if (subjectDAO != null)
            {
                subjects = subjectDAO.getAll();
            }

        }

        private void loadGroups()
        {

            // wczytujemy grupy


            DB.CoreDAO.GroupDAO groupDAO = DB.DAOFactory.getGroupDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            if (groupDAO != null)
            {
                groups = groupDAO.getAll();
                foreach (var elem in groups)
                {
                    comboBoxGroups.Items.Add(elem.Id + " - " + elem.Name);
                }
                comboBoxGroups.DropDownStyle = ComboBoxStyle.DropDownList;
            }

        }

        private void loadClassrooms()
        {

            // wczytujemy sale
            DB.CoreDAO.ClassroomDAO classroomDAO = DB.DAOFactory.getClassroomDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            classrooms = classroomDAO.getAll();
            foreach (var elem in classrooms)
            {
                comboBoxClassrooms.Items.Add(elem.Id + " - " + elem.Name);
            }
            comboBoxClassrooms.DropDownStyle = ComboBoxStyle.DropDownList;

        }

        private void loadTeachers()
        {

            // wczytujemy prowadzących
            DB.CoreDAO.TeacherDAO teacherDAO = DB.DAOFactory.getTeacherDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            teachers = teacherDAO.getAll();
            foreach (var elem in teachers)
            {
                comboBoxTeachers.Items.Add(elem.Id + " - " + elem.Name);
            }
            comboBoxTeachers.DropDownStyle = ComboBoxStyle.DropDownList;

        }

        private void loadDays()
        {
            DB.CoreDAO.DayDAO dao = DB.DAOFactory.getDayDAO(ConfigManager.ConfigManager.getConfiguration().Type); ;
            days = dao.getAll();
            grid.ColumnCount = days.Count;
            int i = 0;
            foreach (var day in days)
            {
                grid.Columns[i].Name = day.Name;
                grid.Columns[i].MinimumWidth = columnMinimumWidth;
                i++;
            }

        }


        private void loadHours()
        {
            grid.RowHeadersWidth = 200;

            DB.CoreDAO.ClassHourDAO dao = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type); ;
            classHours = dao.getAll();
            int i = 0;
            foreach (var classHour in classHours)
            {
                string[] rowValues = { };
                grid.Rows.Add(rowValues);
                grid.Rows[i++].HeaderCell.Value =
                    classHour.Begin.ToString().Substring(0, 5) +
                    " - " +
                    classHour.End.ToString().Substring(0, 5)
                    ;

            }

        }

        private void zakończToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void buttonChangePassword_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            // sprawdzenie czy wpisano poprawne stare hasło
            String oldPassword = DB.Authenticator.LogedUser.Password;
            if (DB.MD5Coder.encode(textBoxOldPassword.Text) != oldPassword)
            {
                lblStudSettWarn.ForeColor = Color.Red;
                lblStudSettWarn.Text = "Wpisano błędne stare hasło.";
            }

            // sprawdzenie czy w obu polach wpisano to samo nowe hasło
            else if (textBoxNewPassword1.Text != textBoxNewPassword2.Text)
            {
                lblStudSettWarn.ForeColor = Color.Red;
                lblStudSettWarn.Text = "Wpisane hasła różnią się.";
            }

            // sprawdzenie czy cokolwiek wpisano
            // czy pozwalamy na puste hasła?
            else if (textBoxNewPassword1.Text == "")
            {
                lblStudSettWarn.ForeColor = Color.Red;
                lblStudSettWarn.Text = "Nie wpisano nowego hasła.";
            }

            // jeśli wszystko jest dobrze, to zapisujemy zmianę hasła
            else
            {
                String newPassword = textBoxNewPassword1.Text;

                DB.Domain.Core.User user = DB.Authenticator.LogedUser;
                user.Password = DB.MD5Coder.encode(newPassword);
                DB.CoreDAO.UserDAO dao = DB.DAOFactory.getUserDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                dao.update(user);

                lblStudSettWarn.ForeColor = Color.Green;
                lblStudSettWarn.Text = "Zmieniono hasło.";
            }

            Cursor = Cursors.Default;

        }

        private void comboBoxTeachers_SelectedIndexChanged(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            if (comboBoxTeachers.SelectedIndex != -1)
            {
                comboBoxGroups.SelectedIndex = -1;
                comboBoxClassrooms.SelectedIndex = -1;


                // wybrano prowadzącego
                lblStudBrow1.Text = "Wybrano plan dla prowadzącego: " + comboBoxTeachers.SelectedItem.ToString();
                comboBoxGroups.ResetText();
                comboBoxClassrooms.ResetText();

                int selectedIndex = comboBoxTeachers.SelectedIndex;
                DB.Domain.Core.Teacher teacher = teachers.ElementAt(selectedIndex);

                loadTeacherPlan(teacher);
            }

            Cursor = Cursors.Default;
        }

        private void comboBoxClassrooms_SelectedIndexChanged(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            if (comboBoxClassrooms.SelectedIndex != -1)
            {
                comboBoxGroups.SelectedIndex = -1;
                comboBoxTeachers.SelectedIndex = -1;


                // wybrano salę
                lblStudBrow1.Text = "Wybrano plan dla sali: " + comboBoxClassrooms.SelectedItem.ToString();
                comboBoxGroups.ResetText();
                comboBoxTeachers.ResetText();

                int selectedIndex = comboBoxClassrooms.SelectedIndex;
                DB.Domain.Core.Classroom classroom = classrooms.ElementAt(selectedIndex);

                loadClassroomPlan(classroom);
            }

            Cursor = Cursors.Default;
        }

        private void comboBoxGroups_SelectedIndexChanged(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            if (comboBoxGroups.SelectedIndex != -1)
            {
                comboBoxClassrooms.SelectedIndex = -1;
                comboBoxTeachers.SelectedIndex = -1;

                // wybrano grupę
                lblStudBrow1.Text = "Wybrano plan dla grupy: " + comboBoxGroups.SelectedItem.ToString();
                comboBoxClassrooms.ResetText();
                comboBoxTeachers.ResetText();

                int selectedIndex = comboBoxGroups.SelectedIndex;
                DB.Domain.Core.Group group = groups.ElementAt(selectedIndex);

                loadGroupPlan(group);
            }

            Cursor = Cursors.Default;
        }


        private void loadGroupPlan(DB.Domain.Core.Group g)
        {
            int numberOfRows = classHours.Count;
            int numberOfColumns = days.Count;
            string[,] cells = new string[numberOfRows, numberOfColumns];

            DB.CoreDAO.ScheduleDAO dao = DB.DAOFactory.getScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            IList<DB.Domain.Core.Schedule> list = dao.getByGroup(g);
            foreach (var elem in list)
            {
                DB.Domain.Core.ClassHour classHour = elem.ClassHour;
                int rowNumber = classHours.IndexOf(classHour);
                DB.Domain.Core.Day day = elem.Day;
                int columnNumber = days.IndexOf(day);

                string cell = elem.Subject.Name + "\n" + elem.Teacher.Name + "\n" + elem.Classroom.Name;
                cells[rowNumber, columnNumber] = cell;

            }

            for (int r = 0; r < numberOfRows; r++)
            {
                string[] rowValues = new string[numberOfColumns];
                for (int c = 0; c < numberOfColumns; c++)
                {
                    if (cells[r, c] != null)
                    {
                        rowValues[c] = cells[r, c];
                    }
                    else
                    {
                        rowValues[c] = "\n\n";
                    }
                }
                grid.Rows[r].SetValues(rowValues);
            }

            grid.AutoResizeColumns();
            grid.AutoResizeRows();

        }


        private void loadClassroomPlan(DB.Domain.Core.Classroom cr)
        {
            int numberOfRows = classHours.Count;
            int numberOfColumns = days.Count;
            string[,] cells = new string[numberOfRows, numberOfColumns];

            DB.CoreDAO.ScheduleDAO dao = DB.DAOFactory.getScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            IList<DB.Domain.Core.Schedule> list = dao.getByClassroom(cr);
            foreach (var elem in list)
            {
                DB.Domain.Core.ClassHour classHour = elem.ClassHour;
                int rowNumber = classHours.IndexOf(classHour);
                DB.Domain.Core.Day day = elem.Day;
                int columnNumber = days.IndexOf(day);

                string cell = elem.Subject.Name + "\n" + elem.Teacher.Name + "\n" + elem.Group.Name;
                cells[rowNumber, columnNumber] = cell;

            }

            for (int r = 0; r < numberOfRows; r++)
            {
                string[] rowValues = new string[numberOfColumns];
                for (int c = 0; c < numberOfColumns; c++)
                {
                    if (cells[r, c] != null)
                    {
                        rowValues[c] = cells[r, c];
                    }
                    else
                    {
                        rowValues[c] = "\n\n";
                    }
                }
                grid.Rows[r].SetValues(rowValues);
            }

            grid.AutoResizeColumns();
            grid.AutoResizeRows();

        }



        private void loadTeacherPlan(DB.Domain.Core.Teacher t)
        {
            int numberOfRows = classHours.Count;
            int numberOfColumns = days.Count;
            string[,] cells = new string[numberOfRows, numberOfColumns];

            DB.CoreDAO.ScheduleDAO dao = DB.DAOFactory.getScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            IList<DB.Domain.Core.Schedule> list = dao.getByTeacher(t);
            foreach (var elem in list)
            {
                DB.Domain.Core.ClassHour classHour = elem.ClassHour;
                int rowNumber = classHours.IndexOf(classHour);
                DB.Domain.Core.Day day = elem.Day;
                int columnNumber = days.IndexOf(day);

                string cell = elem.Subject.Name + "\n" + elem.Classroom.Name + "\n" + elem.Group.Name;
                cells[rowNumber, columnNumber] = cell;

            }

            for (int r = 0; r < numberOfRows; r++)
            {
                string[] rowValues = new string[numberOfColumns];
                for (int c = 0; c < numberOfColumns; c++)
                {
                    if (cells[r, c] != null)
                    {
                        rowValues[c] = cells[r, c];
                    }
                    else
                    {
                        rowValues[c] = "\n\n";
                    }
                }
                grid.Rows[r].SetValues(rowValues);
            }

            grid.AutoResizeColumns();
            grid.AutoResizeRows();

        }

        private void deleteHour_Click(object sender, EventArgs e)
        {

        }

        private void add_Click(object sender, EventArgs e)
        {

        }

        private void tabManagingHours_Click(object sender, EventArgs e)
        {

        }

        //============================================================
        //zakladka, zarządzanie godzinami
        //============================================================
        private void addNewHour_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            DB.CoreDAO.ClassHourDAO classHourDao = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);

            DB.Domain.Core.ClassHour cHour = null;
            ConfigManager.Config config = ConfigManager.ConfigManager.getConfiguration();
            if (config.Type == ConfigManager.Mode.School)
            {
                cHour = new DB.Domain.ClassHourSchool();
            }
            else
            {
                cHour = new DB.Domain.ClassHourUniversity();
            }

            cHour.Begin = new TimeSpan(Convert.ToInt32(AddNewHourStart.Value), Convert.ToInt32(AddNEwMinuteStart.Value), 0);
            cHour.End = new TimeSpan(Convert.ToInt32(AddNewHourEnd.Value), Convert.ToInt32(AddNewMinuteEnd.Value), 0);
            cHour.Id = Convert.ToInt32(IDnumericUpDown1.Value);
            Boolean hourIsValid = true;
            Boolean hourAlreadyExists = false;
            if (cHour.End <= cHour.Begin)
            {
                hourIsValid = false;
            }

            //validacja godzin
            foreach (var existingHour in classHours)
            {
                if (cHour.Id == existingHour.Id || (existingHour.Begin.Equals(cHour.Begin) && existingHour.End.Equals(cHour.End)))
                {
                    hourAlreadyExists = true;
                    break;
                }
                if (cHour.End <= existingHour.Begin)
                {
                    if (classHours.IndexOf(existingHour) == 0)
                    {
                        //godzina jest ok
                        break;
                    }
                    else if (cHour.Begin < classHours.ElementAt(classHours.IndexOf(existingHour) - 1).End)
                    {
                        hourIsValid = false;
                        break;
                    }
                }
                else if (classHours.IndexOf(existingHour) == classHours.Count - 1 && cHour.Begin < existingHour.End)
                {
                    hourIsValid = false;
                    break;
                }
            }


            if (hourIsValid && !hourAlreadyExists)
            {
                Debug.Write("Before save: " + cHour.Id);
                classHourDao.save(cHour);
                Debug.Write("After save: " + cHour.Id);
                MessageBox.Show("Dodano Godzinę.");
            }
            else if (!hourIsValid)
            {
                MessageBox.Show("Nie można dodać takiej godziny!");
            }
            else if (hourAlreadyExists)
            {
                MessageBox.Show("Wybrana Godzina już istnieje!");
            }
            fillClassHours();
            Cursor = Cursors.Default;
        }

        private void deleteHour_Click_1(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            Int32 selectedRowCount = gridClassHour.Rows.GetRowCount(DataGridViewElementStates.Selected);
            if (selectedRowCount > 0)
            {
                int selectedIndex = gridClassHour.SelectedRows[0].Index;
                DB.Domain.Core.ClassHour cHour = classHours.ElementAt(selectedIndex);

                DB.CoreDAO.ClassHourDAO classHourDao = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                classHourDao.delete(cHour);
                MessageBox.Show("Usunięto Godzinę!.");
                fillClassHours();
            }
            else
            {
                MessageBox.Show("Proszę zaznaczyć wiersz z godziną do usunięcia.");
            }
            Cursor = Cursors.Default;
        }
        private void fillClassHours()
        {
            loadHours();
            this.gridClassHour.Rows.Clear();

            foreach (var hour in classHours)
            {
                int n = gridClassHour.Rows.Add();
                gridClassHour.Rows[n].Cells[0].Value = hour.Begin;
                gridClassHour.Rows[n].Cells[1].Value = hour.End;
                gridClassHour.Rows[n].Cells[2].Value = hour.Id;
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            Int32 selectedRowCount = gridClassHour.Rows.GetRowCount(DataGridViewElementStates.Selected);
            if (selectedRowCount > 0)
            {
                int selectedIndex = gridClassHour.SelectedRows[0].Index;
                DB.Domain.Core.ClassHour cHour = classHours.ElementAt(selectedIndex);
                DB.Domain.Core.ClassHour pHour = null;
                if (selectedIndex > 0)
                {
                    pHour = classHours.ElementAt(selectedIndex - 1);
                }
                DB.Domain.Core.ClassHour nHour = null;
                if (selectedIndex + 1 < classHours.Count)
                {
                    nHour = classHours.ElementAt(selectedIndex + 1);
                }
                using (smAdmHourEdit smadmHourEdit = new smAdmHourEdit(cHour, pHour, nHour))
                {
                    smadmHourEdit.ShowDialog();
                }
                fillClassHours();
            }
            else
            {
                MessageBox.Show("Proszę zaznaczyć wiersz z godziną do edycji!");
            }
            Cursor = Cursors.Default;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            using (smSubjectAndGroups smSandG = new smSubjectAndGroups())
            {
                smSandG.ShowDialog();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            using (smTeachersAndHours smTandH = new smTeachersAndHours())
            {
                smTandH.ShowDialog();
            }
        }

        private void dtpickFrom_ValueChanged(object sender, EventArgs e)
        {

        }

        private void comboBoxTeacher_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private DB.Domain.Core.Day getDayID(DateTime dateTime)
        {
            string day = "";
            if (dateTime.DayOfWeek == DayOfWeek.Monday)
            {
                day = "Poniedzialek";
            }
            else if (dateTime.DayOfWeek == DayOfWeek.Friday)
            {
                day = "Piatek";
            }
            else if (dateTime.DayOfWeek == DayOfWeek.Saturday)
            {
                day = "Sobota";
            }
            else if (dateTime.DayOfWeek == DayOfWeek.Sunday)
            {
                day = "Niedziela";
            }
            else if (dateTime.DayOfWeek == DayOfWeek.Thursday)
            {
                day = "Czwartek";
            }
            else if (dateTime.DayOfWeek == DayOfWeek.Tuesday)
            {
                day = "Wtorek";
            }
            else if (dateTime.DayOfWeek == DayOfWeek.Wednesday)
            {
                day = "Sroda";
            }
            foreach (var d in days)
            {
                if (d.Name.Equals(day))
                {
                    Debug.Write("getDayID " + d.Name);
                    return d;
                }
            }
            return null;
        }
        private void addNewTeacherInaccessibilityRow(Teacher t, string comboBox)
        {
            //check if (this.emergencyScheduleWeek.DayOfYear / 7 == dtpickFromTeacherInaccessibility.Value.DayOfYear / 7)//
            DateTime start = dtpickFromTeacherInaccessibility.Value;
            DateTime end = dtpickToTeacherInaccessibility.Value;

            DB.Domain.Core.Day day = getDayID(start);
            if (
                //dataPoczatkowa < dataKoncowa
                start < end &&
                //dzien dataPoczatkowa jest dniem odbywajacych sie zajec
                day != null &&
                //dataPoczatkowa && dataKoncowa sa w tym samym tygodniu
                theSameWeek(start, end) &&
                //dataPoczatkaa && pierwsza_data sa w tym samym tygodniu
                theSameWeek(start, this.emergencyScheduleWeek)
                )
            {
                //setujemy emergencyScheduleWeek
                if (start.DayOfYear != end.DayOfYear)
                {

                    //dodanie pierwszego dnia
                    DateTime firstDayEnd = new DateTime(start.Year, start.Month, start.Day, 23, 59, 59);
                    TeacherInaccessibility ti = new TeacherInaccessibility(t, start, firstDayEnd, day, comboBox);
                    this.teacherInnaccessibility.Add(ti);
                    Console.WriteLine("newTI: " + ti.from.ToString() + "-" + ti.to.ToString() + "; Day:" + ti.day.Name + "; Teacher:" + ti.teacher.Name);

                    //petla
                    int difference = end.DayOfYear - start.DayOfYear;
                    for (int i = 1; i <= difference; i++)
                    {
                        DateTime nextDayStart = new DateTime(start.Year, start.Month, start.Day + i, 0, 0, 0);
                        DB.Domain.Core.Day nextDayDAO = getDayID(nextDayStart);
                        if (i == difference && nextDayDAO != null)
                        {
                            TeacherInaccessibility teacherI = new TeacherInaccessibility(t, nextDayStart, end, nextDayDAO, comboBox);
                            this.teacherInnaccessibility.Add(teacherI);
                            Console.WriteLine("newTI: " + teacherI.from.ToString() + "-" + teacherI.to.ToString() + "; Day:" + teacherI.day.Name + "; Teacher:" + teacherI.teacher.Name);
                        }
                        else if (nextDayDAO != null)
                        {
                            DateTime nextDayEnd = new DateTime(start.Year, start.Month, start.Day + i, 23, 59, 59);
                            TeacherInaccessibility teacherI = new TeacherInaccessibility(t, nextDayStart, nextDayEnd, nextDayDAO, comboBox);
                            this.teacherInnaccessibility.Add(teacherI);
                            Console.WriteLine("newTI: " + teacherI.from.ToString() + "-" + teacherI.to.ToString() + "; Day:" + teacherI.day.Name + "; Teacher:" + teacherI.teacher.Name);
                        }

                    }
                }
                else
                {
                    TeacherInaccessibility ti = new TeacherInaccessibility(t, dtpickFromTeacherInaccessibility.Value, dtpickToTeacherInaccessibility.Value, day, comboBox);
                    this.teacherInnaccessibility.Add(ti);
                    Console.WriteLine("ELSE newTI: " + ti.from.ToString() + "-" + ti.to.ToString() + "; Day:" + ti.day.Name + "; Teacher:" + ti.teacher.Name);
                }

                int n = gridTeacherInaccessibility.Rows.Add();
                gridTeacherInaccessibility.Rows[n].Cells[0].Value = comboBox;
                gridTeacherInaccessibility.Rows[n].Cells[1].Value = start.ToString("dd-MM-yyyy HH:mm");
                gridTeacherInaccessibility.Rows[n].Cells[2].Value = end.ToString("dd-MM-yyyy HH:mm");
                gridTeacherInaccessibility.AutoResizeColumns();
                gridTeacherInaccessibility.AutoResizeRows();

            }
            else
            {
                MessageBox.Show("Prosze wybrac daty z tygodnia: " + getWeekStartEndString() + " lub wyczyscic wprowadzone niedostepnosci!");
            }
        }
        public String getWeekStartEndString()
        {
            DateTime dt = this.emergencyScheduleWeek;
            int startOfWeek = dayOfWeekToInt(dt.DayOfWeek);
            long ticksInSecond = TimeSpan.FromSeconds(1).Ticks;
            long ticksInDay = TimeSpan.FromDays(1).Ticks;
            int dayStart = dayOfWeekToInt(dt.DayOfWeek);
            long startTicks = dt.Ticks - dayStart * ticksInDay - dt.Second * ticksInSecond - dt.Minute * 60 * ticksInSecond - dt.Hour * 3600 * ticksInSecond;
            DateTime weekStart = new DateTime(startTicks);
            DateTime weekEnd = new DateTime(startTicks + 7 * ticksInDay - ticksInSecond);
            String st = weekStart.ToString() + " - " + weekEnd.ToString();
            return st;

        }

        int dayOfWeekToInt(DayOfWeek dayOfWeek)
        {
            if (dayOfWeek == DayOfWeek.Monday)
            {
                return 0;
            }
            else if (dayOfWeek == DayOfWeek.Tuesday)
            {
                return 1;
            }
            else if (dayOfWeek == DayOfWeek.Wednesday)
            {
                return 2;
            }
            else if (dayOfWeek == DayOfWeek.Thursday)
            {
                return 3;
            }
            else if (dayOfWeek == DayOfWeek.Friday)
            {
                return 4;
            }
            else if (dayOfWeek == DayOfWeek.Saturday)
            {
                return 5;
            }
            else if (dayOfWeek == DayOfWeek.Sunday)
            {
                return 6;
            }
            throw new Exception("WTF? Exception");
        }

        bool theSameWeek(DateTime first, DateTime second)
        {

            if (first > second)
            {
                DateTime temp = first;
                first = second;
                second = temp;
            }

            int dayOfWeek = this.dayOfWeekToInt(first.DayOfWeek);
            int daySubstraction = second.DayOfYear - (first.DayOfYear - dayOfWeek);
            if (daySubstraction < 7 && daySubstraction >= 0)
            {
                Console.WriteLine("theSameWeek True: " + first.ToString() + "-" + second.ToString());
                return true;
            }
            return false;
        }

        private void buttonAddTeacherInaccessibility_Click(object sender, EventArgs e)
        {
            String comboBox = comboBoxAddTeacherInaccessibility.SelectedItem.ToString();
            foreach (var t in teachers)
            {
                if (comboBox.Equals(t.Id + " - " + t.Name))
                {
                    //DB.Domain.Core.Day day = getDayID(dtpickFromTeacherInaccessibility.Value);
                    //emergencyScheduleWeek is null
                    if (this.boolEmergencyScheduleWeek == false)
                    {
                        this.emergencyScheduleWeek = dtpickFromTeacherInaccessibility.Value;
                        this.boolEmergencyScheduleWeek = true;
                        this.addNewTeacherInaccessibilityRow(t, comboBox);
                    }
                    else
                    {
                        this.addNewTeacherInaccessibilityRow(t, comboBox);
                    }
                }
            }
        }

        private void addNewClassroomInaccessibilityRow(Classroom c, string comboBox)
        {
            DateTime start = dateTimePickerFromClassroomInaccessibility.Value;
            DateTime end = dateTimePickerToClassroomInaccessibility.Value;

            DB.Domain.Core.Day day = getDayID(start);
            if (
                //dataPoczatkowa < dataKoncowa
                start < end &&
                //dzien dataPoczatkowa jest dniem odbywajacych sie zajec
                day != null &&
                //dataPoczatkowa && dataKoncowa sa w tym samym tygodniu
                theSameWeek(start, end) &&
                //dataPoczatkaa && pierwsza_data sa w tym samym tygodniu
                theSameWeek(start, this.emergencyScheduleWeek)
                )
            {
                //setujemy emergencyScheduleWeek
                if (start.DayOfYear != end.DayOfYear)
                {

                    //dodanie pierwszego dnia
                    DateTime firstDayEnd = new DateTime(start.Year, start.Month, start.Day, 23, 59, 59);
                    ClassroomInaccessibility ci = new ClassroomInaccessibility(c, start, firstDayEnd, day, comboBox);
                    this.classroomInaccessibility.Add(ci);
                    Console.WriteLine("newCI: " + ci.from.ToString() + "-" + ci.to.ToString() + "; Day:" + ci.day.Name + "; Classroom:" + ci.classroom.Name);

                    //petla
                    int difference = end.DayOfYear - start.DayOfYear;
                    for (int i = 1; i <= difference; i++)
                    {
                        DateTime nextDayStart = new DateTime(start.Year, start.Month, start.Day + i, 0, 0, 0);
                        DB.Domain.Core.Day nextDayDAO = getDayID(nextDayStart);
                        if (i == difference && nextDayDAO != null)
                        {
                            ClassroomInaccessibility classroomI = new ClassroomInaccessibility(c, nextDayStart, end, nextDayDAO, comboBox);
                            this.classroomInaccessibility.Add(classroomI);
                            Console.WriteLine("newCI: " + classroomI.from.ToString() + "-" + classroomI.to.ToString() + "; Day:" + classroomI.day.Name + "; Classroom:" + classroomI.classroom.Name);
                        }
                        else if (nextDayDAO != null)
                        {
                            DateTime nextDayEnd = new DateTime(start.Year, start.Month, start.Day + i, 23, 59, 59);
                            ClassroomInaccessibility classroomI = new ClassroomInaccessibility(c, nextDayStart, nextDayEnd, nextDayDAO, comboBox);
                            this.classroomInaccessibility.Add(classroomI);
                            Console.WriteLine("newCI: " + classroomI.from.ToString() + "-" + classroomI.to.ToString() + "; Day:" + classroomI.day.Name + "; Classroom:" + classroomI.classroom.Name);
                        }

                    }
                }
                else
                {
                    ClassroomInaccessibility ci = new ClassroomInaccessibility(c, dtpickFromTeacherInaccessibility.Value, dtpickToTeacherInaccessibility.Value, day, comboBox);
                    this.classroomInaccessibility.Add(ci);
                    Console.WriteLine("ELSE newCI: " + ci.from.ToString() + "-" + ci.to.ToString() + "; Day:" + ci.day.Name + "; Classroom:" + ci.classroom.Name);
                }

                int n = dataGridViewClassroomInaccessibility.Rows.Add();
                dataGridViewClassroomInaccessibility.Rows[n].Cells[0].Value = comboBox;
                dataGridViewClassroomInaccessibility.Rows[n].Cells[1].Value = start.ToString("dd-MM-yyyy HH:mm");
                dataGridViewClassroomInaccessibility.Rows[n].Cells[2].Value = end.ToString("dd-MM-yyyy HH:mm");
                dataGridViewClassroomInaccessibility.AutoResizeColumns();
                dataGridViewClassroomInaccessibility.AutoResizeRows();

            }
            else
            {
                MessageBox.Show("Prosze wybrac daty z tygodnia: " + getWeekStartEndString() + " lub wyczyscic wprowadzone niedostepnosci!");
            }
        }


        private void buttonAddClassroomInaccessibility_Click(object sender, EventArgs e)
        {
            String comboBox = comboBoxAddClassroomInaccessibility.SelectedItem.ToString();
            foreach (var c in classrooms)
            {
                if (comboBox.Equals(c.Id + " - " + c.Name))
                {
                    if (this.boolEmergencyScheduleWeek == false)
                    {
                        this.emergencyScheduleWeek = dateTimePickerFromClassroomInaccessibility.Value;
                        this.boolEmergencyScheduleWeek = true;
                        this.addNewClassroomInaccessibilityRow(c, comboBox);
                    }
                    else
                    {
                        this.addNewClassroomInaccessibilityRow(c, comboBox);
                    }
                }
            }
        }


        private bool checkTeachersUnavailability()
        {
            TeacherUnavailabilityDAO teacherUnavailabilityDAO = DB.DAOFactory.getTeacherUnavailabilityDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            IList<DB.Domain.Core.TeacherUnavailability> teachersUnavailability = teacherUnavailabilityDAO.getAll();
           
            //zawezenie do daty
            foreach (var dbtu in teachersUnavailability)
            {
                DateTime dbtuDate = new DateTime(dbtu.Date);
                if (theSameWeek(dbtuDate, this.emergencyScheduleWeek))
                {
                    return false;
                   
                }
            }
            return true;
        }

        private bool checkClassroomsUnavailability()
        {
            ClassroomUnavailabilityDAO classroorUnavailabilityDAO = DB.DAOFactory.getClassroomUnavailabilityDAO(ConfigManager.ConfigManager.getConfiguration().Type);
            IList<DB.Domain.Core.ClassroomUnavailability> classroomsUnavailability = classroorUnavailabilityDAO.getAll();
          

            //zawezenie do daty
            foreach (var dbcu in classroomsUnavailability)
            {
                DateTime dbcuDate = new DateTime(dbcu.Date);
                if (theSameWeek(dbcuDate, this.emergencyScheduleWeek))
                {
                    return false;
                }
            }
            return true;
        }

        private void buttonEmergencySchedule_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            this.buttonAddClassroomInaccessibility.Enabled = false;
            this.buttonAddTeacherInaccessibility.Enabled = false;
            this.buttonClearInaccessibility.Enabled = false;
            this.buttonEmergencySchedule.Enabled = false;
            // Algorytm dla szkoły
            if (this.checkTeachersUnavailability() && this.checkClassroomsUnavailability())
            {
                if (ConfigManager.ConfigManager.getConfiguration().Type == ConfigManager.Mode.School)
                {
                    Algorytm.Algorytm_Tworzenie_dla_Szkoly alg = new Algorytm.Algorytm_Tworzenie_dla_Szkoly(teachers.Count, subjects.Count, groups.Count, classrooms.Count, 5, 10);

                    // Dodanie nauczycieli do algorytmu szkoły
                    foreach (var _nauczyciel in teachers)
                    {
                        //_nauczyciel.
                        int[] _subjects = new int[_nauczyciel.Subjects.Count];
                        for (int i = 0; i < _nauczyciel.Subjects.Count; i++)
                        {
                            //_subjects[i] =
                            _subjects[i] = _nauczyciel.Subjects.ElementAt(i).Id;
                        }

                        HourDAO hDao = DB.DAOFactory.getHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);

                        IList<DB.Domain.Core.Hour> hours = _nauczyciel.Hours;
                        // przerobienie czasu na godziny kolejnych lekcji
                        ClassHourDAO classHourDAO = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);

                        // Zamiana na przedziały
                        IList<Algorytm.Algorytm_Przedzial> _przedzialy = new List<Algorytm.Algorytm_Przedzial>();

                        foreach (var classHour in hours)
                        {
                            IList<Algorytm.Algorytm_Przedzial> _przedzialyGodzinowe = Converter.DomainConverter.getAlgorytm_Przedzial(classHour);

                            //_przedzialy.Concat(_przedzialyGodzinowe).ToList();
                            _przedzialy = _przedzialy.Concat<Algorytm.Algorytm_Przedzial>(_przedzialyGodzinowe).ToList<Algorytm.Algorytm_Przedzial>();
                            // DEBUG
                            //Console.WriteLine("nauczyciel: "+_nauczyciel.Id + " - " + classHour.Begin + " - " + classHour.End );
                        }
                        // DEBUG
                        // wyświetlnie przedziałów

                        Console.WriteLine("Nauczyciel: " + _nauczyciel.Id + ",przedmiotow: " + _nauczyciel.Subjects.Count + ",przedzialy: " + _przedzialy.Count);
                        foreach (var _p in _przedzialy)
                        {
                            Console.WriteLine("Przedzial - d:" + _p.Dzien + "(" + _p.Poczatek + "," + _p.Koniec + ")");
                        }

                        alg.dodaj_nauczyciela(_nauczyciel.Id, 0, _nauczyciel.Subjects.Count, _subjects, _przedzialy.Count, _przedzialy.ToArray());
                    }

                    // Dodanie sal do algorytmu szkoły
                    foreach (var _sala in classrooms)
                    {
                        SubjectDAO subjectDAO = DB.DAOFactory.getSubjectDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                        IList<DB.Domain.Core.Subject> _przedmioty = subjectDAO.getSubjectsByClassroom(_sala);

                        //SubjectDAOSchool subjectDAO = new SubjectDAOSchool();
                        //IList<SubjectSchool> _przedmioty = subjectDAO.getSubjectsByClassroom(_sala);

                        int[] _przedmiotyId = new int[_przedmioty.Count];
                        for (int i = 0; i < _przedmioty.Count; i++)
                        {
                            _przedmiotyId[i] = _przedmioty.ElementAt(i).Id;
                        }

                        //IList<DB.Domain.Subject> _przedmioty = subjectDAO.
                        ClassroomDAO classroomDao = DB.DAOFactory.getClassroomDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                        //alg.dodaj_sale( id_sali, liczba_przed_w_sali, int[] lista_przedmiotów);
                        //Console.WriteLine(_przedmiotyId.ToString());

                        alg.dodaj_sale(_sala.Id, _przedmioty.Count, _przedmiotyId);

                        // DEBUG
                        /*
                        for (int i = 0; i < _przedmioty.Count; i++)
                        {
                            Console.Write(_przedmiotyId[i] + " ");
                        }
                        Console.WriteLine(" Sala: " + _sala.Id + ", przedmiotow: " + _przedmioty.Count);
                        */
                    }

                    // Dodanie klas do algorytmu szkoły
                    if (ConfigManager.ConfigManager.getConfiguration().Type == ConfigManager.Mode.School)
                    {
                        foreach (var _grupa in groups)
                        {
                            // liczba przedmiotów
                            //GroupDAOSchool groupDAO = new GroupDAOSchool();
                            GroupDAO groupDAO = DB.DAOFactory.getGroupDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                            List<Algorytm.Algorytm_Zajecia> _przedmiotyList = new List<Algorytm.Algorytm_Zajecia>();

                            // różne zajęcia
                            int _amount = 0;
                            //Algorytm_Zajecia[] tab_zaj = new Algorytm_Zajecia[_grupa.SubjectsCount.];

                            // DEBUG
                            Console.WriteLine("Grupa: " + _grupa.Id + ", przedmiotow: " + _grupa.SubjectsCount.Count + " - ");
                            foreach (var _przedmiot in _grupa.SubjectsCount)
                            {
                                _amount += _przedmiot.Value;
                                Algorytm.Algorytm_Zajecia algzaj = new Algorytm.Algorytm_Zajecia(_przedmiot.Key.Id, _przedmiot.Value, 1);
                                _przedmiotyList.Add(algzaj);
                                //DEBUG
                                Console.WriteLine("Zajecia: " + _przedmiot.Key.Id + ", ilosc: (" + _przedmiot.Value + ") ");
                            }
                            //IList<Subject> _przedmioty = _grupa.SubjectsCount.Values;
                            //_przedmiotyList = DomainConverter.getAlgorytm_Zajecia(new List<DB.Domain.Core.Subject>(_grupa.SubjectsCount.Keys));

                            alg.dodaj_klase(_grupa.Id, 0, _grupa.SubjectsCount.Count, _amount, _przedmiotyList.ToArray());

                            //DEBUG
                            /*
                            Console.WriteLine("Grupa: " + _grupa.Id + ", przedmiotow: " + _grupa.SubjectsCount.Count + " - ");
                            foreach (var przed in _przedmiotyList)
                            {
                               // Console.Write( przed.
                            }
                             * */
                        }
                    }

                    // Testowanie czy wszaystkie dane są poprawne

                    //start:karmimy starym planem
                    ScheduleDAO scheduleDAO = DB.DAOFactory.getScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                    ClassHourDAO classHourDAO2 = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                    scheduleDAO.getAll();

                    List<Algorytm.Algorytm_Element_wyniku> algorytm_element_wyniku = Converter.DomainConverter.getAlgorytmElementWyniku(scheduleDAO.getAll());
                    alg.Ustaw_obecny_plan(algorytm_element_wyniku);
                    //end:karmimy starym planem

                    //start:karmimy niedostepnoscia nauczyciela
                    foreach (var t in teacherInnaccessibility)
                    {
                        Algorytm.Algorytm_Przedzial algorytm_przedzial = new Algorytm.Algorytm_Przedzial();
                        TimeSpan begin = new TimeSpan(t.from.Hour, t.from.Minute, t.from.Millisecond);
                        TimeSpan end = new TimeSpan(t.to.Hour, t.to.Minute, t.to.Millisecond);
                        DB.Domain.HourSchool hour = new DB.Domain.HourSchool();
                        hour.Day = t.day;
                        hour.Begin = begin;
                        hour.End = end;
                        IList<Algorytm.Algorytm_Przedzial> algorytmPrzedzialList = Converter.DomainConverter.getAlgorytm_Przedzial(hour);
                        foreach (var a in algorytmPrzedzialList)
                        {
                            alg.dodaj_nieobecnosc_nauczyciela(t.teacher.Id, a);
                        }
                    }
                    //end:karmimy niedostepnoscia nauczyciela

                    //start:karmimy niedostepnoscia sal
                    foreach (var cr in classroomInaccessibility)
                    {
                        Algorytm.Algorytm_Przedzial algorytm_przedzial = new Algorytm.Algorytm_Przedzial();
                        TimeSpan begin = new TimeSpan(cr.from.Hour, cr.from.Minute, cr.from.Millisecond);
                        TimeSpan end = new TimeSpan(cr.to.Hour, cr.to.Minute, cr.to.Millisecond);
                        DB.Domain.HourSchool hour = new DB.Domain.HourSchool();
                        hour.Day = cr.day;
                        hour.Begin = begin;
                        hour.End = end;
                        IList<Algorytm.Algorytm_Przedzial> algorytmPrzedzialList = Converter.DomainConverter.getAlgorytm_Przedzial(hour);
                        foreach (var a in algorytmPrzedzialList)
                        {
                            alg.dodaj_niedostepnosc_sali(cr.classroom.Id, a);
                        }
                    }
                    //end:karmimy niedostepnoscia nauczyciela


                    // Usuwanie starego planu gdy wszystko ok
                    //ScheduleDAO scheduleDAO = DB.DAOFactory.getScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                    //scheduleDAO.deleteAll();
                    // generowanie PLANU

                    alg.Generuj_plan_awaryjny();
                    Algorytm.Algorytm_Wyniki algWyniki = alg.Pobierz_Plan();
                    List<Algorytm.Algorytm_Element_wyniku> wynikiAlg = algWyniki.Pobierz_Plan_Awaryjny();

                    Console.WriteLine("ILOSC WYNIKOW START*******************************************************************************************" + wynikiAlg.Count);
                    foreach (var wynik in wynikiAlg)
                    {
                        Console.WriteLine(wynik.Dzien + " " + wynik.Godzina + " " + wynik.Klasa + " " + wynik.Nauczyciel + " " + wynik.Przedmiot);
                    }

                    Console.WriteLine("ILOSC WYNIKOW END*******************************************************************************************" + wynikiAlg.Count);
                    //alg.drukuj_graf(0);

                    DB.Domain.ScheduleSchool plan = new DB.Domain.ScheduleSchool();

                    if (algWyniki.Czy_wszystko_poszlo_dobrze)
                    {
                       
                            IList<EmergencySchedule> emergencySchedule = Converter.DomainConverter.getEmergencySchedule(wynikiAlg, this.emergencyScheduleWeek);
                            EmergencyScheduleDAO emergencyScheduleDAO = DB.DAOFactory.getEmergencyScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);

                            //save teacherInnaccessibility
                            TeacherUnavailabilityDAO teachersUnavailabilityDAO = DB.DAOFactory.getTeacherUnavailabilityDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                            foreach (var ti in teacherInnaccessibility)
                            {
                               /* IList<DB.Domain.Core.TeacherUnavailability> tiObjects = ti.getTeacherUnavailabilityObjects();
                                foreach (var tiObject in tiObjects)
                                {
                                    teachersUnavailabilityDAO.saveOrUpdate(tiObject);
                                }*/
                            }
                            //save classroomInaccessibility
                            ClassroomUnavailabilityDAO classroomsUnavailabilityDAO = DB.DAOFactory.getClassroomUnavailabilityDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                            foreach (var ci in classroomInaccessibility)
                            {
                                /*IList<DB.Domain.Core.ClassroomUnavailability> ciObjects = ci.getClassroomUnavailabilityObjects();
                                foreach (var ciObject in ciObjects)
                                {
                                    classroomsUnavailabilityDAO.saveOrUpdate(ciObject);
                                }*/
                            }
                            //save emergencySchedule
                            foreach (var es in emergencySchedule)
                            {
                                emergencyScheduleDAO.saveOrUpdate(es);
                            }

                            MessageBox.Show("Wygenerowano plan!");
                    }
                    else
                    {
                        MessageBox.Show("Plan nie został wygenerowany pomyślnie!");
                    }

                    //Drukowanie wyników
                    //alg.drukuj_wierzcholki();
                    //alg.drukuj_nauczycieli();
                    //alg.drukuj_graf(1);

                }
                ////////////////////////////////////////////////////////////////////////////////////////////////
                //UCZELNIA
                ////////////////////////////////////////////////////////////////////////////////////////////////
                else if (ConfigManager.ConfigManager.getConfiguration().Type == ConfigManager.Mode.University)
                {
                    /***************************************************************************************************************************************
                     * ********************************************** UCZELNIA UCZELNIE UCZELNIA ***********************************************************/
                    // Algorytm dla uczelni
                    //MessageBox.Show("ALgorytm dla uczelni!", "Algorytm dla uczelni");

                    //TODO pododawać wszystko dla algorytmu
                    int l_grup_przed = 0;
                    foreach (var sub in subjects)
                    {
                        l_grup_przed += sub.Count;
                    }

                    // Liczba przedmiotów które nie mogą odbywać się w tym samym czasie

                    Algorytm.Algorytm_Tworzenie_dla_Uczelni algUczelnia = new Algorytm.Algorytm_Tworzenie_dla_Uczelni(teachers.Count, subjects.Count, categories.Count, classrooms.Count, 5, 10);

                    /*
                    MessageBox.Show("Dane dla algorytmu: \n" +
                        "ilość przedmitów: " + subjects.Count + "\n" +
                        "ilość grup prze: " + l_grup_przed + "\n"
                        , "Algorytm dla uczelni");

                    */
                    // Dodawanie nauczyciela
                    // Dodanie nauczycieli do algorytmu szkoły
                    foreach (var _nauczyciel in teachers)
                    {
                        // Teraz przedmioty są zappisane gdzieindziej
                        int[] _subjects = new int[_nauczyciel.Subjects.Count];
                        //for (int i = 0; i < _nauczyciel.Subjects.Count; i++)
                        //{
                        //    _subjects[i] = _nauczyciel.Subjects.ElementAt(i).Id;
                        //}
                        for (int i = 0; i < _nauczyciel.SubjectCount.Count; i++)
                        {
                            _subjects[i] = _nauczyciel.SubjectCount.Keys.ElementAt(i).Id;
                        }


                        HourDAO hDao = DB.DAOFactory.getHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                        IList<DB.Domain.Core.Hour> hours = _nauczyciel.Hours;
                        // przerobienie czasu na godziny kolejnych lekcji
                        ClassHourDAO classHourDAO = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                        // Zamiana na przedziały
                        //IList<Algorytm_Przedzial> _przedzialy = new List<Algorytm_Przedzial>();

                        IList<Algorytm.Algorytm_Przedzial> _przedzialy = Converter.DomainConverter.getAlgorytm_Przedzial2(hours);
                        /*
                        foreach (var classHour in hours)
                        {
                            IList<Algorytm_Przedzial> _przedzialyGodzinowe = DomainConverter.getAlgorytm_Przedzial(classHour);
                            _przedzialy = _przedzialy.Concat<Algorytm_Przedzial>(_przedzialyGodzinowe).ToList<Algorytm_Przedzial>();
                            // DEBUG

                            //Console.WriteLine("nauczyciel: "+_nauczyciel.Id + " - " + classHour.Begin + " - " + classHour.End );
                        }
                         * */
                        // DEBUG
                        // wyświetlnie przedziałów
                        /*
                        Console.WriteLine("Nauczyciel: " + _nauczyciel.Id + ",przedmiotow: " + _nauczyciel.Subjects.Count + ",przedzialy: " + _przedzialy.Count);
                        foreach (var _p in _przedzialy)
                        {
                            Console.WriteLine("Przedzial - d:" + _p.Dzien + "(" + _p.Poczatek + "," + _p.Koniec + ")");
                        }
                        */

                        //Algorytm_Para_Studia algPara = new Algorytm_Para_Studia(
                        List<Algorytm.Algorytm_Para_Studia> prowPrzedmioty = new List<Algorytm.Algorytm_Para_Studia>();
                        //foreach( var sub in _nauczyciel.Subjects) {
                        //    //
                        //    //Algorytm_Para_Studia para = new Algorytm_Para_Studia( sub.Id, sub.Count);
                        //    Algorytm_Para_Studia para = new Algorytm_Para_Studia(sub.Id, 3);
                        //    prowPrzedmioty.Add( para);
                        //}

                        foreach (var sub in _nauczyciel.SubjectCount)
                        {
                            //
                            //Algorytm_Para_Studia para = new Algorytm_Para_Studia( sub.Id, sub.Count);
                            Algorytm.Algorytm_Para_Studia para = new Algorytm.Algorytm_Para_Studia(sub.Key.Id, sub.Value);
                            prowPrzedmioty.Add(para);
                        }

                        Algorytm.Algorytm_Nauczyciel nauczyciel = new Algorytm.Algorytm_Nauczyciel(_nauczyciel.Id, 0, _nauczyciel.Subjects.Count, prowPrzedmioty, _przedzialy.Count, _przedzialy.ToArray());

                        algUczelnia.Dodaj_nauczyciela(nauczyciel);
                        //algUczelnia.dodaj_nauczyciela(_nauczyciel.Id, 0, _nauczyciel.Subjects.Count, _subjects, _przedzialy.Count, _przedzialy.ToArray());
                    }
                    // Dodanie sal do algorytmu szkoły
                    foreach (var _sala in classrooms)
                    {
                        SubjectDAO subjectDAO = DB.DAOFactory.getSubjectDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                        IList<DB.Domain.Core.Subject> _przedmioty = subjectDAO.getSubjectsByClassroom(_sala);

                        int[] _przedmiotyId = new int[_przedmioty.Count];
                        for (int i = 0; i < _przedmioty.Count; i++)
                        {
                            _przedmiotyId[i] = _przedmioty.ElementAt(i).Id;
                        }
                        ClassroomDAO classroomDao = DB.DAOFactory.getClassroomDAO(ConfigManager.ConfigManager.getConfiguration().Type);

                        Algorytm.Algorytm_Sala sala = new Algorytm.Algorytm_Sala(_sala.Id, _przedmioty.Count, _przedmiotyId, true);


                        //algUczelnia.dodaj_sale(_sala.Id, _przedmioty.Count, _przedmiotyId);
                        algUczelnia.Dodaj_sale(sala);

                        // DEBUG
                        /*
                        for (int i = 0; i < _przedmioty.Count; i++)
                        {
                            Console.Write(_przedmiotyId[i] + " ");
                        }
                        Console.WriteLine(" Sala: " + _sala.Id + ", przedmiotow: " + _przedmioty.Count);
                        */
                    }

                    // Dodawanie przedmiotów
                    foreach (var przed in subjects)
                    {
                        Algorytm.Algorytm_Przedmiot przedmiot = new Algorytm.Algorytm_Przedmiot(przed.Id, przed.Count, przed.Time);
                        algUczelnia.Dodaj_przedmiot(przedmiot);
                        //algUczelnia.Dodaj_przedmiot(
                    }

                    // Dodanie nadgrup do przedmiotów

                    foreach (var cat in categories)
                    {
                        /*
                        List<int> idki = new List<int>();
                        foreach (var prze in cat.Subjects)
                        {
                            idki.Add(prze.Id);
                        }
                        */

                        List<Subject> subs = new List<Subject>(cat.Subjects);
                        List<int> idki = subs.ConvertAll<int>(x => x.Id);
                        //int[] _subjects = new int[cat.Subjects.Count];
                        //for (int i = 0; i < cat.Subjects.Count; i++)
                        //{
                        //    //_subjects[i] =
                        //    _subjects[i] = cat.Subjects.ElementAt(i).Id;
                        //}
                        //Algorytm_Grupa_Przedmiotow gr = new Algorytm_Grupa_Przedmiotow(cat.Id, _subjects.ToList);

                        //List<int> idki = ((List<Subject>)cat.Subjects).ConvertAll(x => x.Id);
                        Algorytm.Algorytm_Grupa_Przedmiotow gr = new Algorytm.Algorytm_Grupa_Przedmiotow(cat.Id, idki);

                        algUczelnia.Dodaj_Grupe_Przedmiotow(gr);
                    }

                    // Testowanie czy wszaystkie dane są poprawne

                    //start:karmimy starym planem
                    ScheduleDAO scheduleDAO = DB.DAOFactory.getScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                    ClassHourDAO classHourDAO2 = DB.DAOFactory.getClassHourDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                    scheduleDAO.getAll();

                    List<Algorytm.Algorytm_Element_wyniku> algorytm_element_wyniku = Converter.DomainConverter.getAlgorytmElementWyniku(scheduleDAO.getAll());
                    algUczelnia.Ustaw_obecny_plan(algorytm_element_wyniku);
                    //end:karmimy starym planem

                    //start:karmimy niedostepnoscia nauczyciela
                    foreach (var t in teacherInnaccessibility)
                    {
                        Algorytm.Algorytm_Przedzial algorytm_przedzial = new Algorytm.Algorytm_Przedzial();
                        TimeSpan begin = new TimeSpan(t.from.Hour, t.from.Minute, t.from.Millisecond);
                        TimeSpan end = new TimeSpan(t.to.Hour, t.to.Minute, t.to.Millisecond);
                        DB.Domain.HourUniversity hour = new DB.Domain.HourUniversity();
                        hour.Day = t.day;
                        hour.Begin = begin;
                        hour.End = end;
                        IList<Algorytm.Algorytm_Przedzial> algorytmPrzedzialList = Converter.DomainConverter.getAlgorytm_Przedzial(hour);
                        foreach (var a in algorytmPrzedzialList)
                        {
                            algUczelnia.dodaj_nieobecnosc_nauczyciela(t.teacher.Id, a);
                        }
                    }
                    //end:karmimy niedostepnoscia nauczyciela

                    //start:karmimy niedostepnoscia sal
                    foreach (var cr in classroomInaccessibility)
                    {
                        Algorytm.Algorytm_Przedzial algorytm_przedzial = new Algorytm.Algorytm_Przedzial();
                        TimeSpan begin = new TimeSpan(cr.from.Hour, cr.from.Minute, cr.from.Millisecond);
                        TimeSpan end = new TimeSpan(cr.to.Hour, cr.to.Minute, cr.to.Millisecond);
                        DB.Domain.HourUniversity hour = new DB.Domain.HourUniversity();
                        hour.Day = cr.day;
                        hour.Begin = begin;
                        hour.End = end;
                        IList<Algorytm.Algorytm_Przedzial> algorytmPrzedzialList = Converter.DomainConverter.getAlgorytm_Przedzial(hour);
                        foreach (var a in algorytmPrzedzialList)
                        {
                            algUczelnia.dodaj_niedostepnosc_sali(cr.classroom.Id, a);
                        }
                    }
                    //end:karmimy niedostepnoscia nauczyciela


                    // Usuwanie starego planu gdy wszystko ok
                    //ScheduleDAO scheduleDAO = DB.DAOFactory.getScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                    //scheduleDAO.deleteAll();
                    // generowanie PLANU

                    algUczelnia.Generuj_plan_awaryjny();
                    Algorytm.Algorytm_Wyniki algWyniki = algUczelnia.Pobierz_Plan();
                    List<Algorytm.Algorytm_Element_wyniku> wynikiAlg = algWyniki.Pobierz_Plan_Awaryjny();

                    Console.WriteLine("ILOSC WYNIKOW START*******************************************************************************************" + wynikiAlg.Count);
                    foreach (var wynik in wynikiAlg)
                    {
                        Console.WriteLine(wynik.Dzien + " " + wynik.Godzina + " " + wynik.Klasa + " " + wynik.Nauczyciel + " " + wynik.Przedmiot);
                    }

                    Console.WriteLine("ILOSC WYNIKOW END*******************************************************************************************" + wynikiAlg.Count);

                    if (algWyniki.Czy_wszystko_poszlo_dobrze)
                    {

                        IList<EmergencySchedule> emergencySchedule = Converter.DomainConverter.getEmergencySchedule(wynikiAlg, this.emergencyScheduleWeek);
                        EmergencyScheduleDAO emergencyScheduleDAO = DB.DAOFactory.getEmergencyScheduleDAO(ConfigManager.ConfigManager.getConfiguration().Type);

                        //save teacherInnaccessibility
                        TeacherUnavailabilityDAO teachersUnavailabilityDAO = DB.DAOFactory.getTeacherUnavailabilityDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                        foreach (var ti in teacherInnaccessibility)
                        {
                           /* IList<DB.Domain.Core.TeacherUnavailability> tiObjects = ti.getTeacherUnavailabilityObjects();
                            foreach (var tiObject in tiObjects)
                            {
                                teachersUnavailabilityDAO.saveOrUpdate(tiObject);
                            }*/
                        }
                        //save classroomInaccessibility
                        ClassroomUnavailabilityDAO classroomsUnavailabilityDAO = DB.DAOFactory.getClassroomUnavailabilityDAO(ConfigManager.ConfigManager.getConfiguration().Type);
                        foreach (var ci in classroomInaccessibility)
                        {
                           /* IList<DB.Domain.Core.ClassroomUnavailability> ciObjects = ci.getClassroomUnavailabilityObjects();
                            foreach (var ciObject in ciObjects)
                            {
                                classroomsUnavailabilityDAO.saveOrUpdate(ciObject);
                            }*/
                        }
                        //save emergencySchedule
                        foreach (var es in emergencySchedule)
                        {
                            emergencyScheduleDAO.saveOrUpdate(es);
                        }

                        MessageBox.Show("Wygenerowano plan!");
                    }
                    else
                    {
                        MessageBox.Show("Plan nie został wygenerowany pomyślnie!");
                    }
                }
            }
            else {
                MessageBox.Show("Plan Awaryjny dla tygodnia " + getWeekStartEndString() + " juz istnieje! Prosze najpierw usunac plan awaryjny na ten tydzien");
            }
            Cursor = Cursors.Default;
            this.buttonAddClassroomInaccessibility.Enabled = true;
            this.buttonAddTeacherInaccessibility.Enabled = true;
            this.buttonClearInaccessibility.Enabled = true;
            this.buttonEmergencySchedule.Enabled = true;
        }

        private void butShowEmergencySchedule_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            smEmergencyScheduleForm emergencyScheduleForm = new smEmergencyScheduleForm();
            emergencyScheduleForm.Show();
            Cursor = Cursors.Default;
        }

        private void clearInaccessibility_Click(object sender, EventArgs e)
        {
            //dataGridViewClassroomInaccessibility
            //gridTeacherInaccessibility
            gridTeacherInaccessibility.Rows.Clear();
            dataGridViewClassroomInaccessibility.Rows.Clear();
            this.teacherInnaccessibility.Clear();
            this.classroomInaccessibility.Clear();
            this.boolEmergencyScheduleWeek = false;


        }

        //============================================================
    }
}
